package com.cskaoyan.javase.oop3._2inner._5anonymous._0introduction;

/**
 * 匿名内部类:
 *
 * 我们已经使用过匿名对象了，
 * 匿名对象的含义是这个对象是没有名字，没有引用指向它。
 * 那么匿名内部类，指的就是这个内部类没有名字。
 * 当然成员内部类和静态内部类没法没有名字，所以匿名内部类指的是"没有名字的局部内部类"。是一种特殊的局部内部类。
 * 并且匿名内部类是局部内部类的简化形式,简化的原因在于它直接创建了对象,所以语法会更简洁一点.
 *
 * 匿名内部类:
 *      1.特殊的局部内部类,仍然定义在方法等局部位置,仍然在作用域内部生效
 *      2.它和局部内部类的成员特点一致,有些许区别
 * 语法:
 *      new 类名/接口名(){
 *          // 匿名子类的类体
 *      };
 * 解释:
 *  类名可以是普通类,也可以是抽象类.
 *      1.匿名内部类,
 *          是一个匿名类,这个匿名类是语法中类名/接口名的子类/实现类,所以匿名内部类的语法中隐含继承或实现.
 *      2.既然是一个匿名类,如果不创建对象,后面又怎么用它呢?
 *          所以匿名内部类的语法,实际上是直接创建了这个匿名子类的对象
 *          所以匿名内部类实际上应该叫"匿名内部类对象",这个语法整体表示一个子类对象,而不是一个类
 *      3.匿名内部类语法中的大括号是匿名子类的类体,那么它就可以重写父类方法,也可以定义自身成员.
 *
 *
 * 匿名内部类对象的使用:
 *      1.可以直接使用
 *          直接在匿名内部类对象的语法后面调用方法,访问成员等等.
 *          这种用法,实际上是:
 *              匿名的匿名子类对象
 *
 *      2.用引用接收,然后在使用.
 *          只能用父类引用接收
 *          就是语法中的类名或者接口名
 *          接收完了,就用引用来调用方法,访问成员等等.
 *
 *  以上两种方式,它们的优缺点各自是什么呢?
 *      优点:
 *          1.直接使用匿名内部类对象
 *              a.简单快捷,不需要接收直接用
 *              b.可以访问匿名子类的独有成员
 *          2.引用接收再使用
 *              引用接收就可以多次使用匿名内部类对象了
 *      缺点:
 *          1.直接使用匿名内部类对象
 *              a.一次性的
 *          2.引用接收再使用
 *              使用的引用是父类引用
 *              所以无法直接访问子类独有成员
 *              而且是真的无法访问
 *              因为没法做强转
 *              因为子类是匿名子类,无法强转
 *
 *  以上,就是匿名内部类对象的基本使用.
 *
 * @since 16:10
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 在局部位置创建匿名内部类对象
        // 1.创建A的子类对象
        new A() {
            // 匿名子类的类体
            @Override
            void test() {
                System.out.println("hello world!");
            }

            void test2(){
                System.out.println("我是匿名子类的独有方法!");
            }
        }.test2();

        // 2.创建抽象类BaseB的子类对象
        BaseB bb = new BaseB() {
            @Override
            public void test() {
                System.out.println("我是抽象类的匿名内部类对象");
            }
        };
        bb.test();

        // 3.创建接口IA的子类对象
        new IA() {
            @Override
            public void test() {
                System.out.println("我是接口的匿名内部类对象");
            }
        };
    }
}

class A {
    void test() {
        System.out.println("A");
    }
}

abstract class BaseB {
    public abstract void test();
}

interface IA {
    void test();
}